cd /EAP5_HOME/jboss-eap5.1/seam/examples/booking ~/tools/apache-ant-1.8.2/bin/ant explode
This is a step-by-step how-to guide on porting the Seam Booking application binaries from EAP5.1 to WildFly 8. Although there are better approaches for migrating applications, the purpose of this document is to show the types of issues you might encounter when migrating an application and how to debug and resolve those issues.
For this example, the application EAR is deployed to the JBOSS_HOME/standalone/deployments directory with no changes other than extracting the archives so we can modify the XML files contained within them.
Build the EAR
cd /EAP5_HOME/jboss-eap5.1/seam/examples/booking ~/tools/apache-ant-1.8.2/bin/ant explode
Copy the EAR to the JBOSS_HOME deployments directory:
cp -r EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.ear AS7_HOME/standalone/deployments/ cp -r EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.war AS7_HOME/standalone/deployments/jboss-seam.ear cp -r EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.jar AS7_HOME/standalone/deployments/jboss-seam.ear
Start the WildFly server and check the log. You will see:
INFO [org.jboss.as.deployment] (DeploymentScanner-threads - 1) Found jboss-seam-booking.ear in deployment directory. To trigger deployment create a file called jboss-seam-booking.ear.dodeploy
Create an empty file with the name jboss-seam-booking.ear.dodeploy and copy it into the deployments directory. In the log, you will now see the following, indicating that it is deploying:
INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment of "jboss-seam-booking.ear" INFO [org.jboss.as.server.deployment] (MSC service thread 1-3) Starting deployment of "jboss-seam-booking.jar" INFO [org.jboss.as.server.deployment] (MSC service thread 1-6) Starting deployment of "jboss-seam.jar" INFO [org.jboss.as.server.deployment] (MSC service thread 1-2) Starting deployment of "jboss-seam-booking.war"
At this point, you will first encounter your first deployment error. In the next section, we will step through each issue and how to debug and resolve it.
When you deploy the application, the log contains the following error:
ERROR \[org.jboss.msc.service.fail\] (MSC service thread 1-1) MSC00001: Failed to start service jboss.deployment.subunit."jboss-seam-booking.ear"."jboss-seam-booking.war".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.subunit."jboss-seam-booking.ear"."jboss-seam-booking.war".POST_MODULE: Failed to process phase POST_MODULE of subdeployment "jboss-seam-booking.war" of deployment "jboss-seam-booking.ear" (.. additional logs removed ...) Caused by: java.lang.ClassNotFoundException: javax.faces.FacesException from \[Module "deployment.jboss-seam-booking.ear:main" from Service Module Loader\] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191)
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class javax.faces.FacesException and you need to explicitly add the dependency.
Find the module name for that class in the AS7_HOME/modules directory by looking for a path that matches the missing class. In this case, you will find 2 modules that match:
javax/faces/api/main javax/faces/api/1.2
Both modules have the same module name: “javax.faces.api” but one in the main directory is for JSF 2.0 and the one located in the 1.2 directory is for JSF 1.2. If there was only one module available, we could simply create a MANIFEST.MF file and added the module dependency. But in this case, we want to use the JSF 1.2 version and not the 2.0 version in main, so we need to be able to specify one and exclude the other. To do this, we create a jboss-deployment-structure.xml file in the EAR META-INF/ directory that contains the following data:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
In the "deployment" section, we add the dependency for the javax.faces.api for the JSF 1.2 module. We also add the dependency for the JSF 1.2 module in the sub-deployment section for the WAR and exclude the module for JSF 2.0.
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC00001: Failed to start service jboss.deployment.unit."jboss-seam-booking.ear".INSTALL: org.jboss.msc.service.StartException in service jboss.deployment.unit."jboss-seam-booking.ear".INSTALL: Failed to process phase INSTALL of deployment "jboss-seam-booking.ear" (.. additional logs removed ...) Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.Log from [Module "deployment.jboss-seam-booking.ear.jboss-seam-booking.war:main" from Service Module Loader]
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class org.apache.commons.logging.Log and you need to explicitly add the dependency.
Find the module name for that class in the JBOSS_HOME/modules/ directory by looking for a path that matches the missing class. In this case, you will find one module that matches the path org/apache/commons/logging/. The module name is “org.apache.commons.logging”.
Modify the jboss-deployment-structure.xml to add the module dependency to the deployment section of the file.
<module name="org.apache.commons.logging" export="true"/>
The jboss-deployment-structure.xml should now look like this:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> <module name="org.apache.commons.logging" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/seam-booking]] (MSC service thread 1-3) Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener: java.lang.NoClassDefFoundError: org/dom4j/DocumentException (... additional logs removed ...) Caused by: java.lang.ClassNotFoundException: org.dom4j.DocumentException from [Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader]
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class org.dom4j.DocumentException.
Find the module name in the JBOSS_HOME/modules/ directory by looking for the org/dom4j/DocumentException. The module name is “org.dom4j”.
Modify the jboss-deployment-structure.xml to add the module dependency to the deployment section of the file.
<module name="org.dom4j" export="true"/>
The jboss-deployment-structure.xml file should now look like this:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> <module name="org.apache.commons.logging" export="true"/> <module name="org.dom4j" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/seam-booking]] (MSC service thread 1-6) Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener: java.lang.RuntimeException: Could not create Component: org.jboss.seam.international.statusMessages (... additional logs removed ...) Caused by: java.lang.ClassNotFoundException: org.hibernate.validator.InvalidValue from [Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader]
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class org.hibernate.validator.InvalidValue.
There is a module “org.hibernate.validator”, but the JAR does not contain the org.hibernate.validator.InvalidValue class, so adding the module dependency will not resolve this issue.
In this case, the JAR containing the class was part of the EAP 5.1 deployment. We will look for the JAR that contains the missing class in the EAP5_HOME/jboss-eap-5.1/seam/lib/ directory. To do this, open a console and type the following:
cd EAP5_HOME/jboss-eap-5.1/seam/lib grep 'org.hibernate.validator.InvalidValue' `find . -name '*.jar'`
The result shows:
Binary file ./hibernate-validator.jar matches Binary file ./test/hibernate-all.jar matches
In this case, we need to copy the hibernate-validator.jar to the jboss-seam-booking.ear/lib/ directory:
cp EAP5_HOME/jboss-eap-5.1/seam/lib/hibernate-validator.jar jboss-seam-booking.ear/lib
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
INFO [javax.enterprise.resource.webcontainer.jsf.config] (MSC service thread 1-7) Unsanitized stacktrace from failed start...: com.sun.faces.config.ConfigurationException: Factory 'javax.faces.application.ApplicationFactory' was not configured properly. at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:296) [jsf-impl-2.0.4-b09-jbossorg-4.jar:2.0.4-b09-jbossorg-4] (... additional logs removed ...) Caused by: javax.faces.FacesException: org.jboss.seam.jsf.SeamApplicationFactory at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:606) [jsf-api-1.2_13.jar:1.2_13-b01-FCS] (... additional logs removed ...) at com.sun.faces.config.processor.FactoryConfigProcessor.verifyFactoriesExist(FactoryConfigProcessor.java:294) [jsf-impl-2.0.4-b09-jbossorg-4.jar:2.0.4-b09-jbossorg-4] ... 11 more Caused by: java.lang.InstantiationException: org.jboss.seam.jsf.SeamApplicationFactory at java.lang.Class.newInstance0(Class.java:340) [:1.6.0_25] at java.lang.Class.newInstance(Class.java:308) [:1.6.0_25] at javax.faces.FactoryFinder.getImplGivenPreviousImpl(FactoryFinder.java:604) [jsf-api-1.2_13.jar:1.2_13-b01-FCS] ... 16 more
The com.sun.faces.config.ConfigurationException and java.lang.InstantiationException indicate a dependency issue. In this case, it is not as obvious.
We need to find the module that contains the com.sun.faces classes. While there is no com.sun.faces module, there are are two com.sun.jsf-impl modules. A quick check of the jsf-impl-1.2_13.jar in the 1.2 directory shows it contains the com.sun.faces classes.
As we did with the javax.faces.FacesException ClassNotFoundException, we want to use the JSF 1.2 version and not the JSF 2.0 version in main, so we need to be able to specify one and exclude the other. We need to modify the jboss-deployment-structure.xml to add the module dependency to the deployment section of the file. We also need to add it to the WAR subdeployment and exclude the JSF 2.0 module. The file should now look like this:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> <module name="com.sun.jsf-impl" slot="1.2" export="true"/> <module name="org.apache.commons.logging" export="true"/> <module name="org.dom4j" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> <module name="com.sun.jsf-impl" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> <module name="com.sun.jsf-impl" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/seam-booking]] (MSC service thread 1-1) Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener: java.lang.RuntimeException: com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED! org.apache.commons.collections.ArrayStack from [Module "deployment.jboss-seam-booking.ear:main" from Service Module Loader] (... additional logs removed ...) Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.ArrayStack from [Module "deployment.jboss-seam-booking.ear:main" from Service Module Loader]
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class org.apache.commons.collections.ArrayStack.
Find the module name in the JBOSS_HOME/modules/ directory by looking for the org/apache/commons/collections path. The module name is “org.apache.commons.collections”.
Modify the jboss-deployment-structure.xml to add the module dependency to the deployment section of the file.
<module name="org.apache.commons.collections" export="true"/>
The jboss-deployment-structure.xml file should now look like this:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> <module name="com.sun.jsf-impl" slot="1.2" export="true"/> <module name="org.apache.commons.logging" export="true"/> <module name="org.dom4j" export="true"/> <module name="org.apache.commons.collections" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> <module name="com.sun.jsf-impl" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> <module name="com.sun.jsf-impl" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": org.jboss.msc.service.StartException in service jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": Failed to start service at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1786) (... log messages removed ...) Caused by: javax.persistence.PersistenceException: [PersistenceUnit: bookingDatabase] Unable to build EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:903) {... log messages removed ...) Caused by: org.hibernate.HibernateException: could not instantiate RegionFactory [org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge] at org.hibernate.cfg.SettingsFactory.createRegionFactory(SettingsFactory.java:355) (... log messages removed ...) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_25] (... log messages removed ...) Caused by: org.hibernate.cache.CacheException: could not instantiate CacheProvider [org.hibernate.cache.HashtableCacheProvider] at org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.java:68) ... 20 more Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.HashtableCacheProvider from [Module "org.hibernate:main" from local module loader @12a3793 (roots: /home/sgilda/tools/jboss7/modules)] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191) (... log messages removed ...)
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class org.hibernate.cache.HashtableCacheProvider.
There is no module for “org.hibernate.cache”. In this case, the JAR containing the class was part of the EAP 5.1 deployment. We will look for the JAR that contains the missing class in the EAP5_HOME/jboss-eap-5.1/seam/lib/ directory.
To do this, open a console and type the following:
cd EAP5_HOME/jboss-eap-5.1/seam/lib grep 'org.hibernate.validator.InvalidValue' `find . -name '*.jar'`
The result shows:
Binary file ./hibernate-core.jar matches Binary file ./test/hibernate-all.jar matches
In this case, we need to copy the hibernate-core.jar to the jboss-seam-booking.ear/lib/ directory:
cp EAP5_HOME/jboss-eap-5.1/seam/lib/hibernate-core.jar jboss-seam-booking.ear/lib
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
When you deploy the application, the log contains the following error:
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC00001: Failed to start service jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": org.jboss.msc.service.StartException in service jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": Failed to start service at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1786) (... log messages removed ...) Caused by: javax.persistence.PersistenceException: [PersistenceUnit: bookingDatabase] Unable to build EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:903) (... log messages removed ...) Caused by: org.hibernate.HibernateException: could not instantiate RegionFactory [org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge] at org.hibernate.cfg.SettingsFactory.createRegionFactory(SettingsFactory.java:355) (... log messages removed ...) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_25] (... log messages removed ...) Caused by: org.hibernate.cache.CacheException: could not instantiate CacheProvider [org.hibernate.cache.HashtableCacheProvider] at org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.java:68) ... 20 more Caused by: java.lang.ClassCastException: org.hibernate.cache.HashtableCacheProvider cannot be cast to org.hibernate.cache.spi.CacheProvider at org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.java:65) ... 20 more
A ClassCastException can be a result of many problems. If you look at this exception in the log, it appears the class org.hibernate.cache.HashtableCacheProvider extends org.hibernate.cache.spi.CacheProvider and is being loaded by a different class loader than the class it extends. The org.hibernate.cache.HashtableCacheProvider class is in in the hibernate-core.jar and is being loaded by the application class loader. The class it extends, org.hibernate.cache.spi.CacheProvider, is in the org/hibernate/main/hibernate-core-4.0.0.Beta1.jar and is implicitly loaded by that module.
This is not obvious, but due to changes in Hibernate 4, this problem is caused by a backward compatibility issue due moving the HashtableCacheProvider class into another package. This class was moved from the org.hibernate.cache package to the org.hibernate.cache.internal package. If you don't remove the hibernate.cache.provider_class property from the persistence.xml file, it will force the Seam application to bundle the old Hibernate libraries, resulting in ClassCastExceptions, In WildFly, you should move away from using HashtableCacheProvider and use Infinispan instead.
In WildFly, you need to comment out the hibernate.cache.provider_class property in the jboss-seam-booking.jar/META-INF persistence.xml file as follows:
<!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/> -->
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
At this point, the application should deploy without errors, but when you access the URL “http://localhost:8080/seam-booking/” in a browser and attempt "Account Login", you will get a runtime error “The page isn't redirecting properly”. In the next section, we will step through each runtime issue and how to debug and resolve it.
The application deploys successfully, but when you access the URL “http://localhost:8080/seam-booking/” in a browser, you get “The page isn't redirecting properly” and the log contains the following error:
SEVERE [org.jboss.seam.jsf.SeamPhaseListener] (http--127.0.0.1-8080-1) swallowing exception: java.lang.IllegalStateException: Could not start transaction at org.jboss.seam.jsf.SeamPhaseListener.begin(SeamPhaseListener.java:598) [jboss-seam.jar:] (... log messages removed ...) Caused by: org.jboss.seam.InstantiationException: Could not instantiate Seam component: org.jboss.seam.transaction.synchronizations at org.jboss.seam.Component.newInstance(Component.java:2170) [jboss-seam.jar:] (... log messages removed ...) Caused by: javax.naming.NameNotFoundException: Name 'jboss-seam-booking' not found in context '' at org.jboss.as.naming.util.NamingUtils.nameNotFoundException(NamingUtils.java:109) (... log messages removed ...)
A NameNotFoundException indications a JNDI naming issue. JNDI naming rules have changed in WildFly and we need to modify the lookup names to follow the new rules.
To debug this, look earlier in the server log trace to what JNDI binding were used. Looking at the server log we see this:
15:01:16,138 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named RegisterAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register java:app/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register java:module/RegisterAction!org.jboss.seam.example.booking.Register java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction java:app/jboss-seam-booking.jar/RegisterAction java:module/RegisterAction 15:01:16,138 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named BookingListAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/BookingListAction!org.jboss.seam.example.booking.BookingList java:app/jboss-seam-booking.jar/BookingListAction!org.jboss.seam.example.booking.BookingList java:module/BookingListAction!org.jboss.seam.example.booking.BookingList java:global/jboss-seam-booking/jboss-seam-booking.jar/BookingListAction java:app/jboss-seam-booking.jar/BookingListAction java:module/BookingListAction 15:01:16,138 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named HotelBookingAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking java:app/jboss-seam-booking.jar/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking java:module/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction java:app/jboss-seam-booking.jar/HotelBookingAction java:module/HotelBookingAction 15:01:16,138 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named AuthenticatorAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/AuthenticatorAction!org.jboss.seam.example.booking.Authenticator java:app/jboss-seam-booking.jar/AuthenticatorAction!org.jboss.seam.example.booking.Authenticator java:module/AuthenticatorAction!org.jboss.seam.example.booking.Authenticator java:global/jboss-seam-booking/jboss-seam-booking.jar/AuthenticatorAction java:app/jboss-seam-booking.jar/AuthenticatorAction java:module/AuthenticatorAction 15:01:16,139 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named ChangePasswordAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/ChangePasswordAction!org.jboss.seam.example.booking.ChangePassword java:app/jboss-seam-booking.jar/ChangePasswordAction!org.jboss.seam.example.booking.ChangePassword java:module/ChangePasswordAction!org.jboss.seam.example.booking.ChangePassword java:global/jboss-seam-booking/jboss-seam-booking.jar/ChangePasswordAction java:app/jboss-seam-booking.jar/ChangePasswordAction java:module/ChangePasswordAction 15:01:16,139 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named HotelSearchingAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching java:app/jboss-seam-booking.jar/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching java:module/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelSearchingAction java:app/jboss-seam-booking.jar/HotelSearchingAction java:module/HotelSearchingAction 15:01:16,140 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named EjbSynchronizations in deployment unit subdeployment "jboss-seam.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations java:app/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations java:module/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations java:global/jboss-seam-booking/jboss-seam/EjbSynchronizations java:app/jboss-seam/EjbSynchronizations java:module/EjbSynchronizations 15:01:16,140 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named TimerServiceDispatcher in deployment unit subdeployment "jboss-seam.jar" of deployment "jboss-seam-booking.ear" are as follows: java:global/jboss-seam-booking/jboss-seam/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispatcher java:app/jboss-seam/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispatcher java:module/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispatcher java:global/jboss-seam-booking/jboss-seam/TimerServiceDispatcher java:app/jboss-seam/TimerServiceDispatcher java:module/TimerServiceDispatcher
We need to modify the WAR's lib/components.xml file to use the new JNDI bindings. In the log, note the EJB JNDI bindings all start with "java:app/jboss-seam-booking.jar"
Replace the <core:init> element as follows:
<!-- <core:init jndi-pattern="jboss-seam-booking/#{ejbName}/local" debug="true" distributable="false"/> --> <core:init jndi-pattern="java:app/jboss-seam-booking.jar/#{ejbName}" debug="true" distributable="false"/>
Next, we need to add the EjbSynchronizations and TimerServiceDispatcher JNDI bindings. Add the following component elements to the file:
<component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/> <component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
The components.xml file should now look like this:
<?xml version="1.0" encoding="UTF-8"?> <components xmlns="http://jboss.com/products/seam/components" xmlns:core="http://jboss.com/products/seam/core" xmlns:security="http://jboss.com/products/seam/security" xmlns:transaction="http://jboss.com/products/seam/transaction" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.2.xsd http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.2.xsd http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.2.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd"> <!-- <core:init jndi-pattern="jboss-seam-booking/#{ejbName}/local" debug="true" distributable="false"/> --> <core:init jndi-pattern="java:app/jboss-seam-booking.jar/#{ejbName}" debug="true" distributable="false"/> <core:manager conversation-timeout="120000" concurrent-request-timeout="500" conversation-id-parameter="cid"/> <transaction:ejb-transaction/> <security:identity authenticate-method="#{authenticator.authenticate}"/> <component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/> <component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/> </components>
Redeploy the application by deleting the standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank jboss-seam-booking.ear.dodeploy file in the same directory.
At this point, the application should deploy and run without error. When you access the URL “http://localhost:8080/seam-booking/” in a browser, you will be able to login successfully.
Access the URL “http://localhost:8080/seam-booking/” in a browser and login with demo/demo. You should the Booking welcome page.
Although it would be much more efficient to determine dependencies in advance and add the implicit dependencies in one step, this exercise shows how problems appear in the log and provides some information on how to debug and resolve them.
The following is a summary of changes made to the application when migrating it to WildFly:
We created a jboss-deployment-structure.xml file in the EAR's META-INF/ directory. We added "dependencies" and "exclusions" to resolve ClassNotFoundExceptions. This file contains the following data:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0"> <deployment> <dependencies> <module name="javax.faces.api" slot="1.2" export="true"/> <module name="com.sun.jsf-impl" slot="1.2" export="true"/> <module name="org.apache.commons.logging" export="true"/> <module name="org.dom4j" export="true"/> <module name="org.apache.commons.collections" export="true"/> </dependencies> </deployment> <sub-deployment name="jboss-seam-booking.war"> <exclusions> <module name="javax.faces.api" slot="main"/> <module name="com.sun.jsf-impl" slot="main"/> </exclusions> <dependencies> <module name="javax.faces.api" slot="1.2"/> <module name="com.sun.jsf-impl" slot="1.2"/> </dependencies> </sub-deployment> </jboss-deployment-structure>
We copied the following JARs from the EAP5_HOME/jboss-eap-5.1/seam/lib/ directory to the jboss-seam-booking.ear/lib/ directory to resolve ClassNotFoundExceptions:
hibernate-core.jar hibernate-validator.jar
We modified the {{jboss-seam-booking.jar/META-INF/persistence.xml} file as follows.
First, we changed the jta-data-source element to use the Example database that ships with AS7:
<!-- <jta-data-source>java:/bookingDatasource</jta-data-source> --> <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
Next, we commented out the hibernate.cache.provider_class property:
<!-- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/> -->
We modified the WAR's lib/components.xml file to use the new JNDI bindings
We replaced the <core:init> existing element as follows:
<!-- <core:init jndi-pattern="jboss-seam-booking/#{ejbName}/local" debug="true" distributable="false"/> --> <core:init jndi-pattern="java:app/jboss-seam-booking.jar/#{ejbName}" debug="true" distributable="false"/>
We added component elements for the "EjbSynchronizations" and "TimerServiceDispatcher" JNDI bindings
<component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/> <component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
The unmodified EAR from EAP 5.1 (jboss-seam-booking-eap51.ear.tar.gz) and the EAR as modified to run on AS7 (jboss-seam-booking-as7.ear.tar.gz) are attached to this document.